package com.tian.view.anim.attr_anim

import android.animation.FloatEvaluator
import android.animation.IntEvaluator
import android.animation.ObjectAnimator
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.Fragment
import com.tian.view.databinding.ControlViewListBinding

/**
 * @author tiansongtao, Email:tiansongtao@up366.com
 * @date 2022/12/14 17:57
 *
 * ObjectAnimator 可直接作用于控件的动画， ValueAnimator只是动画自己，需要我们
 * 手动获取值设置给控件，ObjectAnimator可以直接作用于控件的属性，也可以作用于自定义
 * 控件的自定义属性
 *
 * ObjectAnimator使用的控件属性的 set 函数，常用的有：
 * 1. 透明度 alpha  [View.setAlpha]
 * 2. 旋转角度 rotation [View.setRotation], rotationX [View.setRotationX], rotationY [View.setRotationY]
 * 3. 平移： translationX [View.setTranslationX], translationY [View.setTranslationY]
 * 4. 缩放：scaleX [View.setScaleX], scaleY [View.setScaleY]
 */
class ObjectAnimatorFragment : Fragment() {

    private lateinit var b: ControlViewListBinding


    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
        b = ControlViewListBinding.inflate(inflater)
        return b.root
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        (requireActivity() as AppCompatActivity).supportActionBar?.title = "ObjectAnimator"
        initAnimatorAlpha()
        initAnimatorRotation()
        initAnimatorTranslation()
        initAnimatorScale()
        initAnimatorCustom()
        initCommonObject()
        initTestObjectAnimatorGet()
    }


    private fun initAnimatorAlpha() {
        b.mbt1.text = "ObjectAnimator透明度"
        b.mbt1.visibility = View.VISIBLE
        b.mbt1.setOnClickListener {
            /**
             * 第一个参数：动画操作的那个控件
             * 第二个参数：动画操作控件的那个属性，
             * 后面可变参数： 表示的变量值变动范围 从1 到 0 再到1
             */
            val anim = ObjectAnimator.ofFloat(b.mbtShow, "alpha", 1f, 0f, 1f)
            anim.duration = 4000
            anim.start()
        }
    }

    private fun initAnimatorRotation() {
        b.mbt2.text = "ObjectAnimator旋转"
        b.mbt2.visibility = View.VISIBLE
        b.mbt2.setOnClickListener {
            val anim = ObjectAnimator.ofFloat(b.mbtShow, "rotationX", 1f, 180f, 0f)
            anim.duration = 4000
            anim.start()
        }
    }

    private fun initAnimatorTranslation() {
        b.mbt3.text = "ObjectAnimator平移"
        b.mbt3.visibility = View.VISIBLE
        b.mbt3.setOnClickListener {
            val anim = ObjectAnimator.ofFloat(b.mbtShow, "translationX", 0f, 400f, 0f)
            anim.duration = 4000
            anim.start()
        }
    }

    private fun initAnimatorScale() {
        b.mbt4.text = "ObjectAnimator缩放"
        b.mbt4.visibility = View.VISIBLE
        b.mbt4.setOnClickListener {
            val anim = ObjectAnimator.ofFloat(b.mbtShow, "scaleX", 1f, 4f, 1f)
            anim.duration = 4000
            anim.start()
        }
    }

    /**
     * 我们知道 ObjectAnimator 是结合 ValueAnimator 和 控件的 set函数构成的，
     * 所以我们可以只要控件有 set函数我们就可以使用 ObjectAnimator来完成动画效果的设置，
     * 这里我们尝试了一下 setTextSize.
     *
     * 构造函数 [ObjectAnimator.ofObject]
     * ObjectAnimator的流程: 我们了解了 ValueAnimator的流程[ValueAnimatorFragment]， ObjectAnimator类似
     * ObjectAnimtor.ofObject(定义设置参数与范围) --> Interpolator(返回当前进度eg:0.2) ---
     *  --> Evaluator(根据进度生成当前值)  ---> 找到set方法，调用set方法进行设置.
     *
     * 1: 这里我们使用 Evaluator 可以生成适合 set方法参数类型的值，用于调用set时设置参数
     * 2：找set方法：重点， ObjectAnimator.ofObject的第二个参数就是我们设置要找的 set方法，这个方法对应
     *     控件或类的 set方法，这个方法必须是标准的set\get方法，ObjectAnimator会将'set'字符与我们设置的
     *     第二个参数拼接，再找这个set方法。这里ofObject的第二个参数的第一个字母可以忽略大小写。
     *     eg: b.mbtShow.setTextSize(float) -> 对应的ofObject的第二个参数就是 TextSize
     *
     * 同过上面的理解，我们就可以在自定义控件中定义变量的标准set\get方法，并使用ObjectAnimator来动态改变
     * 其值，达到动画效果。
     */
    private fun initAnimatorCustom() {
        b.mbt5.text = "ObjectAnimator自定义"
        b.mbt5.visibility = View.VISIBLE
        b.mbt5.setOnClickListener {
            //这里其实可以直接使用 ObjectAnimator.ofFloat
            val anim = ObjectAnimator.ofObject(b.mbtShow, "TextSize", FloatEvaluator(), 0f, 40f)
            anim.duration = 4000
            anim.start()
        }
    }

    /**
     * ObjectAnimator 也可以使用在普通类， 但不提倡这样用，因为ObjectAnimator的刷新率是根据
     * android系统屏幕刷新率确定的，刷新很快，会有多个重复的值出现。
     * eg: 下面age的设置就会有很多重复的值。
     */
    private fun initCommonObject() {
        b.mbt6.text = "ObjectAnimator使用在普通类里"
        b.mbt6.visibility = View.VISIBLE
        val custom = CustomObjectAnimator()
        b.mbt6.setOnClickListener {
            //第二个参数根据 (initAnimatorCustom)的注释，[CustomObjectAnimator.setAge(int)] 对应的就是 age或Age
            val anim = ObjectAnimator.ofObject(custom, "age", IntEvaluator(), 20)
            anim.duration = 4000
            anim.start()
        }
    }

    /**
     * 我们知道 ofObject 最后是一个可变参数，当我们只设置一个时，这个值就是动画结束值，
     * 而ObjectAnimator在没有起始值是就会调用ofObject第二参数对用的get方法获取初始值，
     * 当没有对应的get方法时，会报警告，初始化默认是0
     */
    private fun initTestObjectAnimatorGet() {
        b.mbt6.text = "ObjectAnimator对变量的get方法"
        b.mbt6.visibility = View.VISIBLE
        b.mbt6.setOnClickListener {
            Log.i("tiansongtao", "initTestObjectAnimatorGet: textSize=${b.mbtShow.textSize}")
            val anim = ObjectAnimator.ofObject(b.mbtShow, "translationX", FloatEvaluator(), 400f)
            anim.duration = 4000
            anim.start()
        }
    }


}